<?php

declare(strict_types=1);

namespace App\Core;

final class RateLimit
{
    private static array $attempts = [];
    private static int $maxAttempts = 5;
    private static int $lockoutTime = 900; // 15分钟

    public static function check(string $key): bool
    {
        self::cleanup();

        if (!isset(self::$attempts[$key])) {
            return true;
        }

        $data = self::$attempts[$key];
        if ($data['count'] >= self::$maxAttempts) {
            return (time() - $data['first_attempt']) >= self::$lockoutTime;
        }

        return true;
    }

    public static function record(string $key): void
    {
        self::cleanup();

        if (!isset(self::$attempts[$key])) {
            self::$attempts[$key] = [
                'count' => 1,
                'first_attempt' => time(),
                'last_attempt' => time()
            ];
        } else {
            self::$attempts[$key]['count']++;
            self::$attempts[$key]['last_attempt'] = time();

            // 如果超过锁定时间，重置计数
            if ((time() - self::$attempts[$key]['first_attempt']) >= self::$lockoutTime) {
                self::$attempts[$key] = [
                    'count' => 1,
                    'first_attempt' => time(),
                    'last_attempt' => time()
                ];
            }
        }

        self::persist();
    }

    public static function getRemainingTime(string $key): int
    {
        if (!isset(self::$attempts[$key])) {
            return 0;
        }

        $data = self::$attempts[$key];
        if ($data['count'] < self::$maxAttempts) {
            return 0;
        }

        $elapsed = time() - $data['first_attempt'];
        return max(0, self::$lockoutTime - $elapsed);
    }

    private static function cleanup(): void
    {
        $now = time();
        foreach (self::$attempts as $key => $data) {
            if (($now - $data['last_attempt']) > self::$lockoutTime) {
                unset(self::$attempts[$key]);
            }
        }
    }

    private static function persist(): void
    {
        $root = defined('APP_ROOT') ? APP_ROOT : dirname(__DIR__, 2);
        $dir = $root . '/storage/logs';
        if (!is_dir($dir)) {
            @mkdir($dir, 0777, true);
        }
        $file = $dir . '/rate_limit.json';
        @file_put_contents($file, json_encode(self::$attempts));
    }

    public static function load(): void
    {
        $root = defined('APP_ROOT') ? APP_ROOT : dirname(__DIR__, 2);
        $file = $root . '/storage/logs/rate_limit.json';
        if (file_exists($file)) {
            $data = @file_get_contents($file);
            if ($data) {
                self::$attempts = json_decode($data, true) ?: [];
            }
        }
    }
}
